home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / x11 / strategy / xsok-1.000 / xsok-1 / xsok-1.01 / src / loadsave.c < prev    next >
C/C++ Source or Header  |  1995-11-03  |  7KB  |  273 lines

  1. /*****************************************************************************/
  2. /*                                         */
  3. /*                                         */
  4. /*    Xsok version 1.00 -- module loadsave.c                     */
  5. /*                                         */
  6. /*    Functions for highscores and loading/saving games.             */
  7. /*    Written by Michael Bischoff (mbi@mo.math.nat.tu-bs.de)             */
  8. /*    November-1994                                 */
  9. /*    see COPYRIGHT.xsok for Copyright details                 */
  10. /*                                         */
  11. /*                                         */
  12. /*****************************************************************************/
  13. #ifndef _POSIX_SOURCE
  14. #define _POSIX_SOURCE
  15. #endif
  16. #include <limits.h>
  17. #include <unistd.h>
  18. #include <time.h>
  19. #include "xsok.h"
  20. #include "version.h"
  21.  
  22. /* code to switch between real and effective user id */
  23. /* we must use the real user id when saving files */
  24.  
  25. void switch_uid(int to_real) {
  26. #ifdef _POSIX_SAVED_IDS
  27.     static int uid_state = -1; /* -1 = unknown, 1 = real, 0 = effective */
  28.     static uid_t real_uid, effective_uid;
  29.     if (uid_state < 0) {
  30.     real_uid = getuid();
  31.     effective_uid = geteuid();
  32.     uid_state = 0;
  33.     }
  34.     if (to_real != uid_state && real_uid != effective_uid) {
  35.     setuid(to_real ? real_uid : effective_uid);
  36.     uid_state = to_real;
  37.     }
  38. #endif
  39. }
  40.  
  41. void setlangdir(void) {
  42.     const char *s;
  43.     char p[100];
  44.     if ((s = getenv("LANG"))) {
  45.     sprintf(p, "%s/%s", xsokdir, s);
  46.     if (!access(p, F_OK)) {        /* langdir does exist */
  47.         langdir = s;
  48.         return;
  49.     }
  50.     }
  51.     langdir = "";
  52. }
  53.  
  54. const char *savedir = NULL;
  55.  
  56. #define NARGS    16    /* score, pushes, moves, time */
  57. #define BUFSIZE    256    /* at least length of longest shortname + 1 */
  58.  
  59. #define MAGIC1    0x741b    /* magic of xsok version 1 */
  60. #define MAGICS    0x741c    /* magic of xsok version 1 simple file */
  61. #define MAGICH    0x741d    /* magic of xsok version 1 highscore file */
  62.  
  63.  
  64. static void read_err(const char *msg) {
  65.     if (gamegraphic) {
  66.     show_message("%s %s", TXT_LOAD_ERR_BASIC, msg);
  67.     cmd_LeaveSok();                /* make it better! */
  68.     }
  69.     fprintf(stderr, "%s %s\n", TXT_LOAD_ERR_BASIC, msg);
  70.     exit(EXIT_FAILURE);
  71. }
  72.  
  73. static void portable_to_internal(long *args, unsigned char *p, int num) {
  74.     do {
  75.     int j;
  76.     *args = 0;
  77.     for (j = 0; j < 4; ++j)
  78.         *args += (long)p[3-j] << (j << 3);
  79.     ++args;
  80.     p += 4;
  81.     } while (--num);
  82. }
  83.  
  84. static void internal_to_portable(unsigned char *p, long *args, int num) {
  85.     do {
  86.     int j;
  87.     memset(p, (*args < 0 ? -1 : 0), 4);
  88.     for (j = 0; j < 4; ++j)
  89.         p[3-j] = (unsigned char)(*args >> (j << 3));
  90.     ++args;
  91.     p += 4;
  92.     } while (--num);
  93. }
  94.  
  95. int highscore[300];
  96.  
  97. void cmd_ReadHighscores(void) {
  98.     FILE *fp;
  99.     char filename[MAXSAVEFILELEN];
  100.     int i;
  101.  
  102.     memset(highscore, 0, sizeof(highscore));
  103.     for (i = 100; i < 300; ++i)
  104.         highscore[i] = 0x7fffffff;
  105.  
  106.     sprintf(filename, "%s/%s.score", savedir, game.type);
  107.     if ((fp = fopen(filename, "rb"))) {
  108.     long p[300];
  109.     unsigned char s[1200];
  110.     fread(s, 4, 300, fp);
  111.     portable_to_internal(p, s, 300);    
  112.     for (i = 0; i < 300; ++i)
  113.         highscore[i] = p[i];
  114.     fclose(fp);
  115.     }
  116.     highscore[0] = MAGICH;
  117. }
  118.  
  119. void WriteHighscores(void) {
  120.     FILE *fp;
  121.     char filename[MAXSAVEFILELEN];
  122.     sprintf(filename, "%s/%s.score", savedir, game.type);
  123.     if ((fp = fopen(filename, "wb"))) {
  124.     int i;
  125.     long p[300];
  126.     unsigned char s[1200];
  127.     for (i = 0; i < 300; ++i)
  128.         p[i] = highscore[i];
  129.     internal_to_portable(s, p, 300);
  130.     fwrite(s, 4, 300, fp);
  131.     fclose(fp);
  132.     }
  133. }
  134.  
  135. void load_game(const char *filename) {
  136.     FILE *fp;
  137.     long args[NARGS];
  138.     int i, remgraphic = gamegraphic;
  139.     unsigned char p[NARGS * 4];
  140.  
  141.     if (gamegraphic)    /* interactive loading */
  142.     graphics_control(Disable);
  143.     OrgLevel();
  144.     if (!(fp = fopen(filename, "rb")))
  145.     read_err(TXT_LOAD_ERR_OPEN);
  146.  
  147.     if (fread(p, 4, 1, fp) != 1)
  148.     read_err(TXT_LOAD_ERR_HEADER);
  149.     portable_to_internal(args, p, 1);
  150.     if (args[0] == MAGICS) {
  151.     fseek(fp, 0L, SEEK_END);
  152.     game.stored_moves = ftell(fp) - 4;
  153.     game.n_moves = game.bookmark = game.stored_moves;
  154.     game.macroStart = -1;
  155.     fseek(fp, 4L, SEEK_SET);
  156.     goto readmoves;
  157.     }
  158.  
  159.     if (args[0] != MAGIC1)
  160.     read_err(TXT_LOAD_ERR_BADMAGIC);
  161.     if (fread(p, 4, NARGS-1, fp) != NARGS-1)
  162.     read_err(TXT_LOAD_ERR_HEADER);
  163.     portable_to_internal(args+1, p, NARGS-1);
  164.  
  165.     game.n_moves = args[3];
  166.     if (args[7] == -1) {    /* loading a game from the alpha version */
  167.     fseek(fp, 32, SEEK_SET);
  168.     game.stored_moves = args[3];
  169.     game.bookmark = game.n_moves;
  170.     game.macroStart = -1;
  171.     } else {
  172.     game.stored_moves = args[7];
  173.     game.macroStart = args[8];
  174.     game.macroEnd = args[9];
  175.     game.macro_x = args[10];
  176.     game.macro_y = args[11];
  177.     game.bookmark = args[12];
  178.     }
  179.     /* skip game type and level */
  180.     fseek(fp, 8L, SEEK_CUR);
  181.  
  182.     /* skip user name */
  183.     i = getc(fp);
  184.     fseek(fp, (long)i, SEEK_CUR);
  185.  
  186.  readmoves:
  187.     if (game.stored_moves > numalloc) {
  188.     numalloc = 256 + (game.stored_moves & ~255);
  189.     movetab = realloc_(movetab, numalloc);
  190.     }
  191.     if (fread(movetab, 1, game.stored_moves, fp) != game.stored_moves)
  192.     read_err(TXT_LOAD_ERR_MOVES);
  193.     fclose(fp);
  194.  
  195.     {   int rem;
  196.     rem = game.n_moves;
  197.     game.n_moves = 0;
  198.     jumpto_movenr(rem);
  199.     }
  200.  
  201.     if (remgraphic)
  202.     graphics_control(EnableAndRedraw);
  203.     cmd_ShowScore();
  204. }
  205.  
  206.  
  207. void save_game(const char *ext) {
  208.     FILE *fp;
  209.     char filename[MAXSAVEFILELEN];
  210.     long args[NARGS];
  211.     int i;
  212.     unsigned char p[4 * NARGS];
  213.  
  214.     compute_score();
  215.     sprintf(filename, "%s/%s.%02d.%s", savedir, game.type, game.level, ext);
  216.     remove(filename);    /* kill any old one first! */
  217.     if (!(fp = fopen(filename, "wb"))) {
  218.     show_message("%s %s", TXT_SAVE_ERR_BASIC, TXT_SAVE_ERR_OPEN);
  219.     goto werr2;
  220.     }
  221.     args[0] = MAGIC1;
  222.     args[1] = game.score;
  223.     args[2] = game.n_pushes;
  224.     args[3] = game.n_moves;
  225.     args[4] = time(NULL);
  226.     args[5] = game.finished;
  227.     args[6] = game.level;
  228.     args[7] = game.stored_moves;
  229.     args[8] = game.macroStart;
  230.     args[9] = game.macroEnd;
  231.     args[10] = game.macro_x;
  232.     args[11] = game.macro_y;
  233.     args[12] = game.bookmark;
  234.     args[13] = args[14] = args[15] = -1;
  235.  
  236.     internal_to_portable(p, args, NARGS);
  237.     if (fwrite(p, 4, NARGS, fp) != NARGS) {
  238.     werr3:
  239.     show_message("%s %s", TXT_SAVE_ERR_BASIC, TXT_SAVE_ERR_HEADER);
  240.     goto werr;
  241.     }
  242.     strncpy(filename, game.type, 8);
  243.     if (fwrite(filename, 1, 8, fp) != 8)
  244.     goto werr3;
  245.  
  246.     i = strlen(username);
  247.     putc(i, fp);
  248.     if (fwrite(username, 1, i, fp) != i)
  249.     goto werr3;
  250.     if (fwrite(movetab, 1, game.stored_moves, fp) != game.stored_moves)
  251.     goto werr3;
  252.  
  253.     fclose(fp);
  254.     show_message(TXT_SAVE_OK);
  255.     play_sound("ok");    /* found no sound file for this. maybe later */
  256.     return;
  257.  
  258. werr:
  259.     fclose(fp);
  260. werr2:
  261.     play_sound("cannotsave");
  262. }
  263.  
  264. void link_game(const char *old, const char *ext) {
  265.     char file1[MAXSAVEFILELEN], file2[MAXSAVEFILELEN];
  266.  
  267.     sprintf(file1, "%s/%s.%02d.%s", savedir, game.type, game.level, old);
  268.     sprintf(file2, "%s/%s.%02d.%s", savedir, game.type, game.level, ext);
  269.     remove(file2);    /* kill any old one first! */
  270.     if (link(file1, file2))
  271.     show_message(TXT_SAVE_ERR_LINK);
  272. }
  273.